package guyubao.com.filter;

import com.auth0.jwt.interfaces.DecodedJWT;
import guyubao.com.entity.UserDetailss;
import guyubao.com.utils.Const;
import guyubao.com.utils.JwtUtils;
import javax.annotation.Resource;
import javax.servlet.FilterChain;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;

/**
 * @author wxa
 */
@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {
//继承OncePerRequestFilter表示每次请求过滤一次，用于快速编写JWT校验规则

    @Resource
    JwtUtils utils;

    @Override
    protected void doFilterInternal(HttpServletRequest request,
                                    HttpServletResponse response,
                                    FilterChain filterChain) throws ServletException, IOException {
        //首先从Header中取出JWT
        String authorization = request.getHeader("Authorization");
        DecodedJWT jwt = utils.resolveJwt(authorization);
        //判断是否包含JWT且格式正确
        if (jwt!=null) {
            String substring = authorization.substring(7);
            //开始解析成UserDetails对象
            UserDetailss user = utils.toUsers(jwt,substring);
            //验证没有问题，那么就可以开始创建Authentication了，这里我们跟默认情况保持一致
            //使用UsernamePasswordAuthenticationToken作为实体，填写相关用户信息进去
            UsernamePasswordAuthenticationToken authentication =
                    new UsernamePasswordAuthenticationToken(user, null, user.getAuthorities());
            authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
            //然后直接把配置好的Authentication塞给SecurityContext表示已经完成验证
            SecurityContextHolder.getContext().setAuthentication(authentication);
            // 之后可以用@RequestAttribute String id来获得id
            request.setAttribute(Const.ATTR_USER_ID,utils.toId(jwt));
            // 之后可以用@RequestAttribute String role来获得身份
            request.setAttribute(Const.ATTR_USER_ROLE,utils.toRole(substring));
            // 之后可以用@RequestAttribute String role来获得身份
            request.setAttribute(Const.ATTR_USER_EMAIL,utils.toEmail(substring));
        }
        //最后放行，继续下一个过滤器
        //因为如果没有验证失败上面是不会给SecurityContext设置Authentication的，后面直接就被拦截掉了
        //而且有可能用户发起的是用户名密码登录请求，这种情况也要放行的，不然怎么登录，所以说直接放行就好
        filterChain.doFilter(request, response);
    }
}